// Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
//
// Licensed under the Mulan PSL v2.
// You can use this file according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the License at
//
//     http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
// FOR MORE DETAILS.

/*
 * @Author: qiulin 1746365080@qq.com
 * @Date: 2024-11-03 21:39:52
 * @LastEditors: qiulin_JXGM ql1746365080@gmail.com
 * @LastEditTime: 2024-12-06 20:02:15
 * @FilePath: /SGSim/DBManager/UnitTest/HDF5/Input/I_ConstraintTest.cpp
 */

#include <vector>

#include <gtest/gtest.h>

#include "DataStructure/Common/Constant.h"

#include "DBManager/DBServiceFactory.h"
#include "DBManager/IService/Input/Constraint/IConstraintSummaryService.h"
#include "DBManager/IService/Input/Constraint/IIndexMappingService.h"
#include "DBManager/IService/Input/Constraint/IMPCADDService.h"
#include "DBManager/IService/Input/Constraint/IMPCService.h"
#include "DBManager/IService/Input/Constraint/IRBAR1Service.h"
#include "DBManager/IService/Input/Constraint/IRBARService.h"
#include "DBManager/IService/Input/Constraint/IRBE1Service.h"
#include "DBManager/IService/Input/Constraint/IRBE2Service.h"
#include "DBManager/IService/Input/Constraint/IRBE3Service.h"
#include "DBManager/IService/Input/Constraint/IRJOINTService.h"
#include "DBManager/IService/Input/Constraint/IRRODService.h"
#include "DBManager/IService/Input/Constraint/IRSPLINEService.h"
#include "DBManager/IService/Input/Constraint/ISPCADDService.h"
#include "DBManager/IService/Input/Constraint/ISPCService.h"
#include "DBManager/IService/Input/Constraint/ISUPORTService.h"
#include "DBManager/IService/Input/Constraint/ITEMPDService.h"
#include "DBManager/IService/Input/Constraint/ITEMPService.h"
#include "DBManager/UnitTest/HDF5/TestDB.h"

using namespace SG::DBManager;

class I_ConstraintTest : public testing::Test
{
  public:
    static const SG::DataStructure::Common::Id sId = 99;
    static void                                SetUpTestSuite ()
    {
        if (DB::ServiceFactory != nullptr)
        {
            DB::ServiceFactory->ClearDatabase ();

            // 对MPC数据的处理
            // 先添加MPC
            SG::DataStructure::FEM::MPCData mpc;
            mpc.m_sId       = sId;
            mpc.m_slaveItem = SG::DataStructure::FEM::MPCData::MPCComponent ();
            // mpc.m_Y         = 1;
            DB::ServiceFactory->get<IMPCService> ()->Add (mpc);
            // 后链接MPCADD
            SG::DataStructure::FEM::MPCADDData mpcadd;
            mpcadd.m_sId     = sId;
            mpcadd.m_subSets = { sId };
            DB::ServiceFactory->get<IMPCADDService> ()->Add (mpcadd);

            // 对SPC数据的处理
            // 先添加SPC
            SG::DataStructure::FEM::SPCData spc;
            spc.m_sId = sId;
            spc.m_g   = 1;
            DB::ServiceFactory->get<ISPCService> ()->Add (spc);

            // 后链接SPCADD
            SG::DataStructure::FEM::SPCADDData spcadd;
            spcadd.m_sId     = sId;
            spcadd.m_subSets = { sId };
            DB::ServiceFactory->get<ISPCADDService> ()->Add (spcadd);
        }
    }
};

TEST_F (I_ConstraintTest, partMapGlobalTest)
{
    std::vector<SG::DataStructure::FEM::IndexMappingData> datas;

    datas.emplace_back (SG::DataStructure::FEM::IndexMappingData (6, { 1, 2, 3 }));
    datas.emplace_back (SG::DataStructure::FEM::IndexMappingData (7, { 4, 5, 6, 7, 8, 9 }));
    datas.emplace_back (SG::DataStructure::FEM::IndexMappingData (8, { 14, 15, 16, 17, 18, 19 }));

    DB::ServiceFactory->get<IIndexMappingService> ()->Add (datas);

    SG::DataStructure::FEM::IndexMapping pgMap = DB::ServiceFactory->get<IIndexMappingService> ()->GetIndexMapping ();

    ASSERT_EQ (pgMap.size (), 3);

    ASSERT_EQ (pgMap[6][0], 1);
    ASSERT_EQ (pgMap[6][1], 2);
    ASSERT_EQ (pgMap[6][2], 3);
    ASSERT_EQ (pgMap[6][3], -1);
    ASSERT_EQ (pgMap[6][4], -1);
    ASSERT_EQ (pgMap[6][5], -1);

    ASSERT_EQ (pgMap[7][0], 4);
    ASSERT_EQ (pgMap[7][1], 5);
    ASSERT_EQ (pgMap[7][2], 6);
    ASSERT_EQ (pgMap[7][3], 7);
    ASSERT_EQ (pgMap[7][4], 8);
    ASSERT_EQ (pgMap[7][5], 9);
}

TEST_F (I_ConstraintTest, MPCTest)
{
    // GetMPCs
    std::vector<SG::DataStructure::FEM::MPCData> _OUT mpcSet;
    DB::ServiceFactory->get<IMPCService> ()->FindBySId (I_ConstraintTest::sId, mpcSet);

    ASSERT_EQ (mpcSet.size (), 1);
}

TEST_F (I_ConstraintTest, MPCAddTest)
{
    auto service = DB::ServiceFactory->get<IMPCADDService> ();
    ASSERT_EQ (service->Size (), 1);
}

TEST_F (I_ConstraintTest, RBAR1Test)
{
    SG::DataStructure::Common::Id const id = 99;

    // 创建对象
    SG::DataStructure::FEM::RBAR1Data obj;
    obj.m_id = id;

    // 获取服务
    auto service = DB::ServiceFactory->get<IRBAR1Service> ();
    // 添加对象
    service->Add (obj);

    ASSERT_EQ (service->Size (), 1);
    ASSERT_EQ (service->FindById (id, obj), SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_EQ (obj.m_id, id);
    ASSERT_EQ (service->GetAllId ().size (), 1);
}

TEST_F (I_ConstraintTest, RBARTest)
{
    SG::DataStructure::Common::Id const id = 99;

    // 创建对象
    SG::DataStructure::FEM::RBARData obj;
    obj.m_id = id;

    // 获取服务
    auto service = DB::ServiceFactory->get<IRBARService> ();
    // 添加对象
    service->Add (obj);

    ASSERT_EQ (service->Size (), 1);
    ASSERT_EQ (service->FindById (id, obj), SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_EQ (obj.m_id, id);
    ASSERT_EQ (service->GetAllId ().size (), 1);
}

TEST_F (I_ConstraintTest, RBE1Test)
{
    SG::DataStructure::Common::Id const id = 99;

    // 创建对象
    SG::DataStructure::FEM::RBE1Data obj;
    obj.m_id = id;

    // 获取服务
    auto service = DB::ServiceFactory->get<IRBE1Service> ();
    // 添加对象
    service->Add (obj);

    ASSERT_EQ (service->Size (), 1);

    ASSERT_EQ (service->FindById (id, obj), SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_EQ (obj.m_id, id);
    ASSERT_EQ (service->GetAllId ().size (), 1);
}

TEST_F (I_ConstraintTest, RBE2Test)
{
    SG::DataStructure::Common::Id const id = 99;

    // 创建对象
    SG::DataStructure::FEM::RBE2Data obj;
    obj.m_id = id;

    // 获取服务
    auto service = DB::ServiceFactory->get<IRBE2Service> ();
    // 添加对象
    service->Add (obj);

    ASSERT_EQ (service->Size (), 1);
    ASSERT_EQ (service->FindById (id, obj), SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_EQ (obj.m_id, id);
    ASSERT_EQ (service->GetAllId ().size (), 1);
}

TEST_F (I_ConstraintTest, RBE3Test)
{
    SG::DataStructure::Common::Id const id = 99;

    // 创建对象
    SG::DataStructure::FEM::RBE3Data obj;
    obj.m_id = id;

    // 获取服务
    auto service = DB::ServiceFactory->get<IRBE3Service> ();
    // 添加对象
    service->Add (obj);

    ASSERT_EQ (service->Size (), 1);
    ASSERT_EQ (service->FindById (id, obj), SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_EQ (obj.m_id, id);
    ASSERT_EQ (service->GetAllId ().size (), 1);
}

TEST_F (I_ConstraintTest, RJointTest)
{
    SG::DataStructure::Common::Id const id = 99;

    // 创建对象
    SG::DataStructure::FEM::RJOINTData obj;
    obj.m_id = id;

    // 获取服务
    auto service = DB::ServiceFactory->get<IRJOINTService> ();
    // 添加对象
    service->Add (obj);

    ASSERT_EQ (service->Size (), 1);
    ASSERT_EQ (service->FindById (id, obj), SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_EQ (obj.m_id, id);
    ASSERT_EQ (service->GetAllId ().size (), 1);
}

TEST_F (I_ConstraintTest, RRODTest)
{
    SG::DataStructure::Common::Id const id = 99;

    // 创建对象
    SG::DataStructure::FEM::RRODData obj;
    obj.m_id = id;

    // 获取服务
    auto service = DB::ServiceFactory->get<IRRODService> ();
    // 添加对象
    service->Add (obj);

    ASSERT_EQ (service->Size (), 1);
    ASSERT_EQ (service->FindById (id, obj), SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_EQ (obj.m_id, id);
    ASSERT_EQ (service->GetAllId ().size (), 1);
}

TEST_F (I_ConstraintTest, RSplineTest)
{
    SG::DataStructure::Common::Id const id = 99;

    // 创建对象
    SG::DataStructure::FEM::RSPLINEData obj;
    obj.m_id = id;

    // 获取服务
    auto service = DB::ServiceFactory->get<IRSPLINEService> ();
    // 添加对象
    service->Add (obj);

    ASSERT_EQ (service->Size (), 1);
    ASSERT_EQ (service->FindById (id, obj), SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_EQ (obj.m_id, id);
    ASSERT_EQ (service->GetAllId ().size (), 1);
}

TEST_F (I_ConstraintTest, SPCAddTest)
{
    auto service = DB::ServiceFactory->get<ISPCADDService> ();
    ASSERT_EQ (service->Size (), 1);
}

TEST_F (I_ConstraintTest, SPCTest)
{
    // GTEST_SKIP();
    //  GetSPCs
    std::vector<SG::DataStructure::FEM::SPCData> _OUT spcSet;

    auto service = DB::ServiceFactory->get<ISPCService> ();

    service->FindBySId (I_ConstraintTest::sId, spcSet);

    ASSERT_EQ (service->Size (), 1);
    ASSERT_EQ (spcSet.size (), 1);
}

TEST_F (I_ConstraintTest, TEMPDTest)
{
    SG::DataStructure::FEM::TEMPDData tempdData;
    tempdData.m_sId = 8;
    tempdData.m_t   = 1.0;
    auto service    = DB::ServiceFactory->get<ITEMPDService> ();
    service->Add (tempdData);

    std::vector<SG::DataStructure::FEM::TEMPDData> _OUT TEMPDSet;
    service->FindBySId (8, TEMPDSet);

    ASSERT_EQ (TEMPDSet.size (), 1);
    ASSERT_NEAR (tempdData.m_t, TEMPDSet[0].m_t, SG::DataStructure::Common::TOLERANCE);
}

TEST_F (I_ConstraintTest, SUPORTTest)
{
    SG::DataStructure::FEM::SUPORTData data;
    data.m_id    = 1;
    auto service = DB::ServiceFactory->get<ISUPORTService> ();
    service->Add (data);

    SG::DataStructure::FEM::SUPORTData _OUT outData;
    service->FindById (1, outData);
    ASSERT_EQ (outData.m_id, 1);

    ASSERT_EQ (service->FindByIndex (0, outData), SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (outData.m_id, 1);

    ASSERT_EQ (service->Size (), 1);
    ASSERT_EQ (service->Count (1), 1);
}

TEST_F (I_ConstraintTest, SummaryTest)
{
    // 获取服务
    auto service = DB::ServiceFactory->get<SG::DBManager::IConstraintSummaryService> ();

    // 添加对象
    auto aaa = service->GetType (99);

    ASSERT_EQ (aaa.size () > 0, true);
}